/************************************************************************
  			hu/myai/triggers/AbstractTrigger.java - Copyright bozbalint

Here you can write a license for your code, some comments or any other
information you want to have in your generated code. To to this simply
configure the "headings" directory in uml to point to a directory
where you have your heading files.

or you can just replace the contents of this file with your own.
If you want to do this, this file is located at

/opt/kde3/share/apps/umbrello/headings/heading.java

-->Code Generators searches for heading files based on the file extension
   i.e. it will look for a file name ending in ".h" to include in C++ header
   files, and for a file name ending in ".java" to include in all generated
   java code.
   If you name the file "heading.<extension>", Code Generator will always
   choose this file even if there are other files with the same extension in the
   directory. If you name the file something else, it must be the only one with that
   extension in the directory to guarantee that Code Generator will choose it.

you can use variables in your heading files which are replaced at generation
time. possible variables are : author, date, time, filename and filepath.
just write %variable_name%

This file was generated on Sat Mar 14 2009 at 12:14:34
The original location of this file is /home/bozbalint/uml-generated-code/hu/myai/triggers/AbstractTrigger.java
 **************************************************************************/

package hu.myai.api.triggers;

import hu.myai.api.indicators.AbstractIndicator;
import hu.myai.api.indicators.AbstractIndicatorConsumer;
import hu.myai.api.indicators.IndicatorInterface;
import hu.myai.api.tick.AbstractTickProvider;
import hu.myai.model.TriggerVO;
import hu.myai.util.pool.IndicatorPool;

import java.util.ArrayList;
import java.util.List;

/**
 * Class AbstractTrigger
 * 
 * Trigger is the second stage after the indicator to evaluate a stock. Aim of a
 * trigger depends on the indicators output check against the pre-implemented
 * correlations and levels
 * 
 * @author bozbalint
 * 
 */

abstract public class AbstractTrigger extends AbstractIndicatorConsumer implements TriggerInterface {

	/**
	 * collection of the registered strategies
	 */
	private List<TriggerConsumerInterface> triggerConsumerList = new ArrayList<TriggerConsumerInterface>();

	/**
	 * This contains the tick reference for the dependent indicators
	 * */
	private AbstractTickProvider tick;

	/**
	 * Constructor, set the name of the trigger and the reference of a tick
	 * provider
	 */
	public AbstractTrigger(String name, AbstractTickProvider tick) {
		this.name = name;
		this.tick = tick;

		// register trigger as a tick consumer
		tick.addTickConsumer(this);

	};

	/**
	 * sets up the required indicator and registers the current trigger
	 * */
	protected String register(AbstractIndicator reqIndicator) {

		if (tick == null) {
			throw new RuntimeException("Tick has not set OR you set it after the parameters");
		}

		// sync the indicator with the pool
		IndicatorInterface regIndicator = IndicatorPool.indicatorManager(reqIndicator, tick);

		// registers the trigger into the indicator so it makes the indicator
		// inputs. registers the indicator to the expected indicator list
		regIndicator.addIndicatorConsumer(this);

		return regIndicator.getName();
	}

	/**
	 * Get the tick with the name
	 */
	public AbstractTickProvider getTick() {
		return tick;
	}

	/**
	 * @return boolean
	 * @param strategy
	 */
	public boolean addTriggerConsumer(TriggerConsumerInterface triggerConsumer) {

		// register itself into the strategy
		if (triggerConsumer.addTriggerNameForCheck(name)) {
			triggerConsumerList.add(triggerConsumer);
			return true;
		} else {
			System.out.println("Error - Consumer cannot be registered: " + triggerConsumer.getName());
			return false;
		}
	}

	/**
	 * @return boolean
	 * @param strategy
	 */
	public boolean removeTriggerConsumer(TriggerConsumerInterface triggerConsumer) {

		// unregister itself from the strategy
		if (triggerConsumer.removeTriggerNameForCheck(name)) {
			triggerConsumerList.remove(triggerConsumer);
			return true;
		} else {
			System.out.println("Error - Consumer cannot be unregistered: " + triggerConsumer.getName());
			return false;
		}
	}

	/**
	 * Backed feature to check the registered listeners
	 */
	public List<TriggerConsumerInterface> getTriggerConsumerList() {
		return triggerConsumerList;

	}

	/**
	 * Backed feature for registered listeners
	 */
	public void setTriggerConsumerList(List<TriggerConsumerInterface> triggerConsumerList) {
		this.triggerConsumerList = triggerConsumerList;
	}

	/**
	 * The method accepts an indicator result. Check if all the expected
	 * indicators added their values to the trigger calculation
	 */
	@Override
	public void startCalculation() {

		// for the calculation only to check if this indicator was the last out
		// of the set.
		if (checkIndicatorCompleteness()) {

			// do the indicator calculation
			TriggerVO trigger = triggerCalculation();

			// clean up the indicator buffer
			indicatorMap.clear();

			// propagate the calculated trade suggestion if the trigger is a
			// valid object
			if (trigger != null && trigger.getTradeType() != 0)
				propegateTrigger(trigger);
		}
	}

	/**
	 * trigger specific calculation. It returns null if no trigger event is
	 * necessary
	 */
	abstract protected TriggerVO triggerCalculation();

	/**
	 * set the trade to all registered strategy
	 * */
	protected void propegateTrigger(TriggerVO trigger) {
		for (TriggerConsumerInterface triggerConsumer : triggerConsumerList) {
			triggerConsumer.addTrigger(name, trigger);
		}
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer("[" + name + " Trigger]\n");
		sb.append("Registered input (indicator): ");
		for (String indicatorName : indicatorNameList) {
			sb.append("\n\t " + indicatorName);
		}
		sb.append("\nRegistered output (strategy): ");
		for (TriggerConsumerInterface triggerConsumer : triggerConsumerList) {
			sb.append("\n\t " + triggerConsumer.getName());
		}

		return sb.toString();
	}
}